package com.sangmo.fts.process.inventory.service;

import com.sangmo.boot.framework.common.errors.ServiceException;
import com.sangmo.boot.framework.common.errors.StandardErrors;
import com.sangmo.boot.framework.common.session.UserSession;
import com.sangmo.boot.framework.data.filter.PageResult;
import com.sangmo.boot.framework.data.filter.PageSearch;
import com.sangmo.boot.framework.data.filter.ValueFilter;
import com.sangmo.boot.framework.plugin.dataview.crud.service.DelegateViewService;
import com.sangmo.boot.framework.plugin.dataview.crud.service.ViewService;
import com.sangmo.fts.basic.model.Goods;
import com.sangmo.fts.basic.service.GoodsService;
import com.sangmo.fts.process.factoring.model.FfContract;
import com.sangmo.fts.process.factoring.model.FfContractItem;
import com.sangmo.fts.process.inventory.interfaces.IfwaybillReceiveRequest;
import com.sangmo.fts.process.inventory.model.IfContract;
import com.sangmo.fts.process.inventory.model.IfWaybill;
import com.sangmo.fts.process.inventory.model.IfWaybillItem;
import com.sangmo.fts.process.inventory.repo.IfWaybillRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class IfWaybillService extends DelegateViewService<IfWaybill> {

    @Autowired
    private IfWaybillEntityService ifWaybillEntityService;

    @Autowired
    private IfWaybillItemEntityService ifWaybillItemEntityService;

    @Autowired
    private IfContractService ifContractService;

    @Autowired
    private GoodsService goodsService;

    @Override
    protected ViewService<IfWaybill> getEntityService() {
        return ifWaybillEntityService;
    }

    public PageResult<IfWaybillItem> listItemsByPage(Long waybillId, PageSearch ps) {
        ps.getFilters().add(new ValueFilter("waybillId", ValueFilter.OP_EQ, waybillId));
        return ifWaybillItemEntityService.search(ps);
    }

    public List<IfWaybillItem> listItemsByWaybillId(Long waybillId) {
        return ifWaybillItemEntityService.listByWaybillId(waybillId);
    }

    public BigDecimal calculateGoodsTotalAmount(Long id) {
        IfWaybill waybill = this.get(id);
        List<IfWaybillItem> waybillItems = ifWaybillItemEntityService.listByWaybillId(waybill.getId());
        BigDecimal contractAmount = BigDecimal.ZERO;
        Map<Long, Goods> goodsMap = goodsService.getAllGoodsMapCache();
        for (IfWaybillItem item : waybillItems) {
            Goods goods = goodsMap.get(item.getGoodsId());
            if (null == goods) {
                throw new ServiceException(StandardErrors.EXTERNAL_ERROR.getStatus(), "error.ifWaybill.goods.amount.wrong");
            }
            contractAmount = contractAmount.add(goods.getPrice().multiply(item.getQuantity()));
        }
        return contractAmount;
    }

    public void ship(Long id) {
        IfWaybill waybill = this.get(id);
        if (!IfWaybill.States.PENDING.equals(waybill.getState())) {
            throw new ServiceException(StandardErrors.CLIENT_ERROR.getStatus(), "error.ifWaybill.has.shipped");
        }
        waybill.setState(IfWaybill.States.DISPATCHED);
        this.save(waybill);
    }

    public void receive(Long id, IfwaybillReceiveRequest request) {
        IfWaybill waybill = this.get(id);
        if (!IfWaybill.States.DISPATCHED.equals(waybill.getState())) {
            throw new ServiceException(StandardErrors.CLIENT_ERROR.getStatus(), "error.ifWaybill.has.received");
        }
        waybill.setState(IfWaybill.States.RECEIVED);
        waybill.setReceiptTime(request.getReceiptTime());
        waybill.setReceiptPlace(request.getReceiptPlace());
        this.save(waybill);
    }

    public PageResult<IfWaybill> selection(PageSearch ps) {
        ps.getFilters().add(new ValueFilter("state", ValueFilter.OP_EQ, IfWaybill.States.RECEIVED));
        return ifWaybillEntityService.search(ps);
    }

}
